﻿using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DK.LinkedList;
public class LinkedList<T>
{
    private LinkedNode<T> HeadNode = new LinkedNode<T>(-1, default(T));

    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="data">数据</param>
    /// <returns></returns>
    public LinkedList<T> Add(T data) 
    {
        LinkedNode<T> temp = HeadNode;
        while (temp.Next != null)
        {
            temp = temp.Next;
        }
        var tempindex = temp.Index;
        temp.Next = new LinkedNode<T>(++tempindex, data);
        return this;
    }

    /// <summary>
    /// 根据位置添加
    /// </summary>
    /// <param name="index">下标</param>
    /// <param name="data">数据</param>
    /// <returns></returns>
    public LinkedList<T> Add(int index,T data)
    {
        var isFind = false;
        LinkedNode<T> temp = HeadNode;
        while (temp.Next != null)
        {
            if (temp.Next.Index == index)
            {
                var newnode = new LinkedNode<T>(index, data);
                newnode.Next = temp.Next;
                temp.Next = newnode;
                temp = newnode;
                isFind = true;
            }

            temp = temp.Next;

            if (isFind) 
            {
                temp.Index++;
            }

        }
        
        return this;
    }


    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="index">下标</param>
    /// <param name="data">数据</param>
    /// <returns></returns>
    public LinkedList<T> Update(int index,T data) 
    {
        Get(index).Data = data;
        return this;
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="index">下标</param>
    /// <returns></returns>
    public LinkedList<T> Delete(int index)
    {
        var isDelete = false;
        LinkedNode<T> temp = HeadNode;
        while (temp.Next != null)
        {
            temp = temp.Next;

            if (isDelete)
            {
                temp.Index--;
            }

            if (temp.Index == index)
            {
                temp.Next = temp.Next?.Next;
                isDelete = true;
            }
            
        }

        return this;
    }

    /// <summary>
    /// 根据下标获取元素
    /// </summary>
    /// <param name="index">下标</param>
    /// <returns></returns>
    public LinkedNode<T> Get(int index) 
    {
        LinkedNode<T> temp = HeadNode;
        while (temp.Next != null)
        {
            temp = temp.Next;
            if (temp.Index == index)
            {
                break;
            }
        }
        return temp;
    }

    /// <summary>
    /// 获取倒数元素(快慢指针版本)
    /// </summary>
    /// <param name="index">倒数</param>
    /// <returns></returns>
    public LinkedNode<T>? GetReverse(int index)
    {
        if (HeadNode.Next == null) 
        {
            throw new NullReferenceException();
        }

        LinkedNode<T> slowtemp = HeadNode;
        LinkedNode<T> fastemp = HeadNode;
        for (int i = 0; i < index; i++)
        {
            if (fastemp.Next == null)
            {
                throw new NullReferenceException();
            }
            fastemp = fastemp.Next;
        }

        while (fastemp.Next != null && slowtemp.Next != null)
        {
            slowtemp = slowtemp.Next;
            fastemp = fastemp.Next;
        }

        return slowtemp;
    }

    /// <summary>
    /// 根据数据获取元素节点，引用类型不能使用
    /// </summary>
    /// <param name="data">数据</param>
    /// <returns></returns>
    public LinkedNode<T> GetOf(T data)
    {
        LinkedNode<T> temp = HeadNode;
        while (temp.Next != null)
        {
            temp = temp.Next;
            if (temp.Data?.GetHashCode() == data?.GetHashCode())
            {
                break;
            }
        }

        return temp;
    }

    /// <summary>
    /// 判空
    /// </summary>
    /// <returns></returns>
    public bool IsNull() 
    {
        return HeadNode.Next != null;
    }

    /// <summary>
    /// 获取大小
    /// </summary>
    /// <returns></returns>
    public int Size()
    {
        int size = 0;
        LinkedNode<T> temp = HeadNode;
        while (temp.Next != null) 
        {
            temp = temp.Next;
            size++;
        }
        return size;
    }

   
    public override string ToString()
    {
        string info = "";
        LinkedNode<T> temp = HeadNode;
        while (temp.Next != null)
        {
            temp = temp.Next;
            info += temp.ToString() + "\n";
        }
        return info;
    }


}

